package com.taxi.driver.module.order.ongoing;

import android.os.Handler;
import android.text.TextUtils;

import com.alibaba.fastjson.JSON;
import com.amap.api.location.AMapLocation;
import com.amap.api.maps.AMapUtils;
import com.amap.api.maps.model.LatLng;
import com.amap.api.navi.model.AMapNaviLocation;
import com.amap.api.navi.model.NaviInfo;
import com.amap.api.services.core.LatLonPoint;
import com.amap.api.services.route.BusRouteResult;
import com.amap.api.services.route.DriveRouteResult;
import com.amap.api.services.route.RideRouteResult;
import com.amap.api.services.route.RouteSearch;
import com.amap.api.services.route.WalkRouteResult;
import com.amap.api.trace.LBSTraceClient;
import com.amap.api.trace.TraceListener;
import com.amap.api.trace.TraceLocation;
import com.qianxx.network.RequestError;
import com.qianxx.utils.RxUtil;
import com.socks.library.KLog;
import com.taxi.driver.BuildConfig;
import com.taxi.driver.R;
import com.taxi.driver.common.AppConfig;
import com.taxi.driver.common.BasePresenter;
import com.taxi.driver.config.BizStatus;
import com.taxi.driver.config.OrderStatus;
import com.taxi.driver.config.PositionType;
import com.taxi.driver.config.TimeType;
import com.taxi.driver.data.amap.AMapManager;
import com.taxi.driver.data.entity.LatLngPoint;
import com.taxi.driver.data.entity.Mileage;
import com.taxi.driver.data.entity.UploadOrderEntity;
import com.taxi.driver.data.order.OrderRepository;
import com.taxi.driver.data.user.UserRepository;
import com.taxi.driver.event.MapEvent;
import com.taxi.driver.event.NetworkEvent;
import com.taxi.driver.event.OrderEvent;
import com.taxi.driver.module.vo.AddressVO;
import com.taxi.driver.module.vo.OrderVO;
import com.taxi.driver.socket.SocketEvent;
import com.taxi.driver.socket.SocketPushContent;
import com.taxi.driver.socket.message.UploadLocationMessage;
import com.taxi.driver.socket.message.base.MessageType;
import com.taxi.driver.util.SpeechUtil;

import org.greenrobot.eventbus.EventBus;
import org.greenrobot.eventbus.Subscribe;
import org.greenrobot.eventbus.ThreadMode;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;

import javax.inject.Inject;

import rx.Observable;
import rx.Subscription;

public class OrderOngoingPresenter extends BasePresenter implements OrderOngoingContract.Presenter {

    private final static int INTERVAL = 5000;
    private final OrderOngoingContract.View mView;
    private final AMapManager mAMapManager;
    private final OrderRepository mOrderRepository;
    private final UserRepository mUserRepository;

    private String mOrderUuid;
    private boolean isFront;
    // 上一次记录里程
    private double mRecordMileage;
    // App 杀死的里程数
    private double mKilledMileage;
    // 当前里程
    private double mCurrentMileage;
    // 误差里程
    private double mErrorMileage;
    // 当前经纬度
    private LatLng mCurrentLatLng;
    // 最新经纬度
    private LatLng mLastLatLng;
    // 轨迹纠偏工具
    private LBSTraceClient mTraceClient;
    // 轨迹纠偏处理中
    private boolean isTraceProcessing = false;
    // 载客时的行驶里程跟踪数据（用于轨迹纠偏）
    private List<TraceLocation> mCarryPassengersTraceList = new ArrayList<>();
    private boolean isSave = false;
    private Handler mHandler = new Handler();

    private int mWaitTime = 0;
    private boolean isOnce = true;
    // 记录订单信息
    private OrderVO mVO;
    private UploadOrderEntity mUploadOrderEntity;
    private Subscription mGetWaitSub;

    private Runnable mTraceRun = new Runnable() {
        @Override
        public void run() {
            mHandler.removeCallbacks(mTraceRun);
            calculateMileage();
            mHandler.postDelayed(mTraceRun, INTERVAL);
        }
    };

    @Inject
    public OrderOngoingPresenter(OrderOngoingContract.View view, AMapManager aMapManager,
                                 OrderRepository orderRepository, UserRepository userRepository) {
        mView = view;
        mAMapManager = aMapManager;
        mOrderRepository = orderRepository;
        mUserRepository = userRepository;
    }

    @Override
    public void onCreate() {
        EventBus.getDefault().register(this);
        mTraceClient = LBSTraceClient.getInstance(mView.getContext());

        // 定时轨迹纠偏，计算行驶里程
        mHandler.postDelayed(mTraceRun, INTERVAL);

        // 获取已行驶里程
        Mileage mileage = mUserRepository.getMileage(mOrderUuid);
        if (mileage != null) {
            LatLng firstPoint = new LatLng(mAMapManager.getLastLocation().getLatitude(), mAMapManager.getLastLocation().getLongitude());
            mRecordMileage = mileage.getMileage();
            LatLng lastPoint = new LatLng(mileage.getLatLngPoint().getLat(), mileage.getLatLngPoint().getLng());
            mKilledMileage = AMapUtils.calculateLineDistance(firstPoint, lastPoint) / 1000.0;
            // 刷新订单里程
            mUploadOrderEntity = new UploadOrderEntity();
            mUploadOrderEntity.mileage = mRecordMileage + mKilledMileage;
            mUploadOrderEntity.currentPoint = firstPoint;
            mUploadOrderEntity.uploadTime = mAMapManager.getLastLocation().getTime();
            mUploadOrderEntity.accuracy = mAMapManager.getLastLocation().getAccuracy();
            EventBus.getDefault().post(new SocketEvent(SocketEvent.SET_SPECIAL_INFO, mUploadOrderEntity));
        }
    }

    @Override
    public void subscribe() {
        super.subscribe();
        isFront = true;

        reqOrderDetail(!mFirstSubscribe);
    }

    @Override
    public void unsubscribe() {
        super.unsubscribe();
        isFront = false;
    }

    @Override
    public void onDestory() {
        mHandler.removeCallbacks(mTraceRun);
        EventBus.getDefault().unregister(this);
        // 通知 SocketService，不要继续上传 orderUuid 和 orderStatus
        EventBus.getDefault().post(new SocketEvent(SocketEvent.ARRIVE_DEST));
    }

    /**
     * 轨迹纠偏，获取较为理想的载客里程(行驶里程)
     */
    private void calculateMileage() {
        if (isTraceProcessing) {
            mTraceClient.destroy();
            mTraceClient = LBSTraceClient.getInstance(mView.getContext());
        }
        if (mTraceClient == null || mCarryPassengersTraceList.size() <= 2) return;
        mTraceClient.stopTrace();
        mTraceClient.queryProcessedTrace(0, mCarryPassengersTraceList,
                LBSTraceClient.TYPE_AMAP, new TraceListener() {
                    @Override
                    public void onRequestFailed(int i, String s) {
                        isTraceProcessing = false;
                    }

                    @Override
                    public void onTraceProcessing(int i, int i1, List<LatLng> list) {
                        isTraceProcessing = true;
                    }

                    /**
                     *
                     * @param i  用于标示一条轨迹，支持多轨迹纠偏，如果多条轨迹调起纠偏接口，则lineID需不同。
                     * @param list 整条轨迹经过纠偏后点的经纬度集合。
                     * @param i1  轨迹经过纠偏后总距离，单位米。
                     * @param i2 该轨迹中间停止时间，以GPS速度为参考，单位秒。
                     */
                    @Override
                    public void onFinished(int i, List<LatLng> list, int i1, int i2) {
                        isTraceProcessing = false;
                        // 判断当前轨迹纠偏和上一次的结果和两点的结果做比较
                        if (mCurrentMileage == 0d) {
                            mCurrentMileage = i1 / 1000d;
                        } else {
                            if (i1 / 1000d > mCurrentMileage + mErrorMileage) {
                                if (i1 / 1000d - mCurrentMileage - mErrorMileage > 0.25) {
                                    mErrorMileage = i1 / 1000d - mCurrentMileage - 0.15;
                                }
                                mCurrentMileage = i1 / 1000d - mErrorMileage;
                            }
                        }
                        // 当前已行驶里程 = 上次退出记录的里程 + 杀死的里程 + 当前纠偏里程
                        double tripDistance = mRecordMileage + mKilledMileage + mCurrentMileage;

                        // 本地存储当前已行驶里程
                        Mileage mileage = new Mileage();
                        mileage.setOrderUuid(mOrderUuid);
                        mileage.setMileage(tripDistance);
                        mileage.setLatLngPoint(new LatLngPoint(
                                mUserRepository.getLatLng().latitude, mUserRepository.getLatLng().longitude));
                        mUserRepository.saveMileage(mileage);

                        // 显示实际行驶里程，仅内测时显示
                        if (BuildConfig.DEBUG) {
                            mView.showMileage(tripDistance);
                        }

                        if (mUploadOrderEntity != null) {
                            mUploadOrderEntity.mileage = tripDistance;
                        }
                        // 发送专车里程信息，通过SocketService上传
                        EventBus.getDefault().post(new SocketEvent(SocketEvent.SET_SPECIAL_INFO, mUploadOrderEntity));

                        KLog.i("已行驶总里程：" + tripDistance +
                                "\n上一次退出APP时的已行驶里程：" + mRecordMileage +
                                "\nAPP退出后中间丢失的里程：" + mKilledMileage +
                                "\n当前行驶的里程：" + mCurrentMileage);
                    }
                }
        );
    }

    @Subscribe(threadMode = ThreadMode.MAIN)
    public void onNetworkEvent(NetworkEvent event) {
        switch (event.type) {
            case NetworkEvent.DISCONNECT:
                mCurrentMileage = 0d;
                mErrorMileage = 0d;
                break;
        }
    }

    @Subscribe(threadMode = ThreadMode.MAIN)
    public void onOrderEvent(OrderEvent event) {
        switch (event.type) {
            case OrderEvent.ORDER_PASSENGER_CANCEL: { //乘客取消订单
                if (event.obj1 == null) return;
                SocketPushContent push = (SocketPushContent) event.obj1;
                if (!push.data.orderUuid.equals(mOrderUuid)) return;
                if (isFront) reqOrderDetail(true); //处于前端，才刷新订单
                if (isOnce) {
                    SpeechUtil.speech(mView.getContext(), push.data.report);
                    isOnce = false;
                }
                break;
            }
            case OrderEvent.SPECIAL_PRICE: //专车订单金额
                if (event.obj1 == null || event.obj2 == null) return;
                String orderUuid = (String) event.obj1;
                if (!orderUuid.equals(mOrderUuid)) return;
                double totalPrice = (double) event.obj2;
                mView.setTotalPrice(totalPrice);
                break;
            case OrderEvent.ORDER_CLOSE: {//后台关闭订单
                if (event.obj1 == null) return;
                SocketPushContent push = (SocketPushContent) event.obj1;
                if (!push.data.orderUuid.equals(mOrderUuid)) return;
                if (!TextUtils.isEmpty(push.orderUuid)) {
                    //设置订单号
                    setOrderUuid(push.orderUuid);
                    //获取订单详情
                    reqOrderDetail(true);
                }
                if (isOnce) {
                    SpeechUtil.speech(mView.getContext(), push.data.report);
                    isOnce = false;
                }
                break;
            }
            case OrderEvent.ORDER_DISTRIBUTE_TO_OTHER: {//订单被改派
                if (event.obj1 == null) return;
                SocketPushContent push = (SocketPushContent) event.obj1;
                if (!push.data.orderUuid.equals(mOrderUuid)) return;
                if (!TextUtils.isEmpty(push.orderUuid)) {
                    //设置订单号
                    setOrderUuid(push.orderUuid);
                    //显示订单改派的弹窗
                    mView.showReassignDialog(push);
                }
                if (isOnce) {
                    SpeechUtil.speech(mView.getContext(), push.data.report);
                    isOnce = false;
                }
                break;
            }
        }
    }

    @Subscribe(threadMode = ThreadMode.MAIN)
    public void onMapEvent(MapEvent event) {
        switch (event.type) {
            case MapEvent.VIEW_RESET: //重置信息显示
                mView.setNaviInfoDisplay(null, null);
                break;
            case MapEvent.VIEW_NAVI_INFO_UPDATE: //设置显示
                if (event.obj1 == null) return;
                NaviInfo naviInfo = (NaviInfo) event.obj1;
                mView.setNaviInfoDisplay(naviInfo.getPathRetainDistance(), naviInfo.getPathRetainTime());
                break;
            case MapEvent.VIEW_LOCATION_CHANGE: //位置改变
                if (event.obj1 == null) return;
                AMapNaviLocation location = (AMapNaviLocation) event.obj1;
                dealwithAMapNaviLocation(location);
                break;
            case MapEvent.VIEW_CHANGE_ADDR: //更改导航目的地
                if (event.obj1 == null) return;
                mView.changeAddress((AddressVO) event.obj1);
                break;
            case MapEvent.VIEW_LOCATION://实时导航时
                if (event.obj1 == null) return;
                dealwithAMapLocation((AMapLocation) event.obj1);
                break;
        }
    }

    @Override
    public void setOrderUuid(String orderUuid) {
        mOrderUuid = orderUuid;
    }

    /**
     * 获取乘客联系电话
     *
     * @return
     */
    @Override
    public String getPassengerPhone() {
        if (mVO == null)
            return "";
        if (!TextUtils.isEmpty(mVO.actualPasMob))
            return mVO.getActualPasMob();//换乘车人电话
        else
            return mVO.getPassengerPhone();//发单人电话
    }

    /**
     * 获取订单详情
     *
     * @param isFromRemote 是否只从服务端获取
     */
    private void reqOrderDetail(final boolean isFromRemote) {
        mSubscriptions.add(
                mOrderRepository.reqOrderDetail(mOrderUuid, isFromRemote)
                        .map(OrderVO::createFrom)
                        .compose(RxUtil.applySchedulers())
                        .doOnNext(vo -> {
                            if (isOnGoing(vo.subStatus)) {
                                EventBus.getDefault().post(new SocketEvent(SocketEvent.BIZ_STATUS, BizStatus.CARRY_PASSENGERS, mOrderUuid));
                            } else {
                                EventBus.getDefault().post(new SocketEvent(SocketEvent.BIZ_STATUS, BizStatus.EMPTY_DRIVING));
                            }
                            if (vo.subStatus == OrderStatus.WAIT_PASSENGER_GET_ON) {
                                getWaitFare();
                            }
                        })
                        .subscribe(vo -> {
                            mVO = vo; // 记录订单详情
                            mView.setDisplay(vo);
                        }, ex -> {
                            if (ex instanceof RequestError) {
                                if (((RequestError) ex).getErrCode() == 20001) {
                                    mView.showReassignedDialog(ex.getMessage());
                                } else {
                                    showNetworkError(ex, R.string.network_error, mView, mUserRepository);
                                }
                            } else {
                                showNetworkError(ex, R.string.network_error, mView, mUserRepository);
                            }
                        }));
    }

    private boolean isOnGoing(int subStatus) {
        return OrderStatus.WAIT_ARRIVE_ORIGIN <= subStatus && subStatus <= OrderStatus.FARE_CONFIRM;
    }

    /**
     * 切换订单状态
     */
    @Override
    public void switchToNextStatus() {
        if (mVO == null || mVO.subStatus == null) {
            mView.toast("订单状态异常");
            return;
        }
        switch (mVO.subStatus) {
            case OrderStatus.WAIT_ARRIVE_ORIGIN: //司机已出发，但未到达"上车地点"
                reqArriveStart(); //到达上车地点
                break;
            case OrderStatus.WAIT_PASSENGER_GET_ON: //司机已到达"上车地点"，但乘客未上车
                reqPassengerGetOn();//接到乘客
                break;
            case OrderStatus.DEPART://到达上车地点前(行程中)
                double tripDistance = mRecordMileage + mKilledMileage + mCurrentMileage;
                if (mUploadOrderEntity != null)
                    mUploadOrderEntity.mileage = tripDistance;
                EventBus.getDefault().post(new SocketEvent(SocketEvent.SET_SPECIAL_INFO_RIGHT_NOW, mUploadOrderEntity));//发送里程信息
                reqArrivedEnd(mVO.typeTime);
                break;
            default:
                mView.resetBtnDisplay(); //重置按键显示
                break;
        }
    }

    @Override
    public AddressVO getNaviDest() {
        if (mVO == null || mVO.subStatus == null) return null;
        AddressVO vo = null;
        switch (mVO.subStatus) {
            case OrderStatus.WAIT_ARRIVE_ORIGIN:
            case OrderStatus.WAIT_PASSENGER_GET_ON:
                vo = new AddressVO();
                vo.setAddress(mVO.originAddress);
                vo.setAddressDetail(mVO.originDetailAddress);
                vo.setLat(mVO.originLat);
                vo.setLng(mVO.originLng);
                break;
            case OrderStatus.DEPART:
                vo = new AddressVO();
                vo.setAddress(mVO.destAddress);
                vo.setAddressDetail(mVO.destDetailAddress);
                vo.setLat(mVO.destLat);
                vo.setLng(mVO.destLng);
                break;
        }
        return vo;
    }

    @Override
    public LatLng getCurrentLatLng() {
        return mUserRepository.getLatLng();
    }

    @Override
    public void setIsDepart(boolean isDepart) {

    }

    @Override
    public void getRealtimeFare(String orderUuid) {
        mSubscriptions.add(
                mOrderRepository.getRealtimeFare(mOrderUuid)
                        .compose(RxUtil.applySchedulers())
                        .subscribe(entity -> mView.showWaitFare(entity.totalFare),
                                ex -> showNetworkError(ex, R.string.network_error, mView, mUserRepository)));
    }

    @Override
    public int driverType() {
        return mUserRepository.getDriverType();
    }

    /**
     * 超时等待费（每分钟获取一次）
     */
    private void getWaitFare() {
        mGetWaitSub = Observable.interval(0, 1, TimeUnit.SECONDS)
                .compose(RxUtil.applySchedulers())
                .subscribe(aLong -> {
                    if (aLong == 0 || mWaitTime % 60 == 0) {
                        mOrderRepository.waitFare(mOrderUuid)
                                .compose(RxUtil.applySchedulers())
                                .subscribe(
                                        entity -> {
                                            mView.showWaitFare(entity.getWaitFare());
                                            mWaitTime = entity.getWaitTime();
                                        }, ex -> showNetworkError(ex, R.string.network_error, mView));
                    }
                    mWaitTime++;
                }, KLog::e);
        mSubscriptions.add(mGetWaitSub);
    }
    // 接到乘客时，停止请求超时等待费
    private void unSubWaitFee() {
        if (mGetWaitSub != null && !mGetWaitSub.isUnsubscribed()) {
            mGetWaitSub.unsubscribe();
        }
    }
    //到达上车地点
    private void reqArriveStart() {
        LatLng Latlng = new LatLng(mAMapManager.getLastLocation().getLatitude(), mAMapManager.getLastLocation().getLongitude());
        //上传当前订单信息
        String uploadText = uploadText(OrderStatus.WAIT_PASSENGER_GET_ON, BizStatus.CARRY_PASSENGERS, Latlng, PositionType.SJDD);

        mSubscriptions.add(
                mOrderRepository.reqDepart(mOrderUuid, uploadText)
                        .compose(RxUtil.applySchedulers())
                        .doOnSubscribe(() -> mView.showLoadingView(true))
                        .doAfterTerminate(mView::hideLoadingView)
                        .doOnNext(s -> {
                            // 语音（到达上车地点）
                            SpeechUtil.speech(mView.getContext(), "到达乘客上车地点，请耐心等待乘客上车");
                            // 获取超时等待费
                            getWaitFare();
                        })
                        .subscribe(s -> {
                            mVO.subStatus = OrderStatus.WAIT_PASSENGER_GET_ON;
                            mView.setDisplay(mVO);
                        }, ex -> {
                            mView.resetBtnDisplay(); //重置按键显示
                            showNetworkError(ex, R.string.network_error, mView, mUserRepository);
                        }));
    }
    //接到乘客
    private void reqPassengerGetOn() {
        LatLng latLng = new LatLng(mAMapManager.getLastLocation().getLatitude(), mAMapManager.getLastLocation().getLongitude());
        String uploadText = uploadText(OrderStatus.DEPART, BizStatus.CARRY_PASSENGERS, latLng, PositionType.CKSC);

        mSubscriptions.add(
                mOrderRepository.reqGetOn(mOrderUuid, 0d, uploadText)
                        .compose(RxUtil.applySchedulers())
                        .doOnSubscribe(() -> mView.showLoadingView(true))
                        .doAfterTerminate(mView::hideLoadingView)
                        .doOnNext(s -> {
                            // 语音（接到乘客）
                            if (AppConfig.isTaxi()) {
                                SpeechUtil.speech(mView.getContext(), "已接到乘客，服务过程请保持安静，并提醒前排乘客系好安全带。" +
                                        "乘客您好，感谢使用出租车，我们将竭诚为您服务，有遇到任何问题，可拨打客服电话。");
                            } else {
                                if (AppConfig.isSpecial()) {
                                    SpeechUtil.speech(mView.getContext(), "已接到乘客，服务过程请保持安静，并提醒前排乘客系好安全带。" +
                                            "乘客您好，感谢使用专车，我们将竭诚为您服务，有遇到任何问题，可拨打客服电话。");
                                } else {
                                    SpeechUtil.speech(mView.getContext(), "已接到乘客，服务过程请保持安静，并提醒前排乘客系好安全带。" +
                                            "乘客您好，感谢使用快车，我们将竭诚为您服务，有遇到任何问题，可拨打客服电话。");
                                }
                            }
                            // 接到乘客时，停止请求超时等待费
                            unSubWaitFee();
                        })
                        .subscribe(s -> {
                            mVO.subStatus = OrderStatus.DEPART;
                            mView.setDisplay(mVO);
                        }, ex -> {
                            mView.resetBtnDisplay(); //重置按键显示
                            showNetworkError(ex, R.string.network_error, mView, mUserRepository);
                        }));
    }
    // 到达目的地
    private void reqArrivedEnd(int orderType) {
        mCurrentLatLng = new LatLng(mAMapManager.getLastLocation().getLatitude(), mAMapManager.getLastLocation().getLongitude());

        reqArriveEnd(orderType);
    }

    // 到达目的地
    private void reqArriveEnd(int orderType) {

        // 日租|半日租订单需要传递具体的地址，通过地理反编码获得具体地址，对于非日租|半日租订单，地址参数是非必须的
        if (orderType == TimeType.DAILY_RENT || orderType == TimeType.HALF_DAY_RENT) {
            mAMapManager.geocodeSearch(mCurrentLatLng)
                    .compose(RxUtil.applySchedulers())
                    .subscribe(address -> {
                        double tripDistance = mRecordMileage + mKilledMileage + mCurrentMileage;
                        String destAddress = address.getPois().get(0).getTitle();
                        String destDetailAddress = address.getFormatAddress();
                        String destCity = address.getCity();
                        double destLng = mCurrentLatLng.longitude;
                        double destLat = mCurrentLatLng.latitude;//// TODO: 2018/5/29 地址做校验
//                         告诉服务端到达目的地
//                        dealWithDistance(tripDistance,destLat,destLng,destAddress,destDetailAddress,destCity);
                        reqArrive(tripDistance, destAddress, destDetailAddress, destCity, destLng, destLat);
                    }, ex -> showNetworkError(ex, R.string.error, mView));
        } else {
            double tripDistance = mRecordMileage + mKilledMileage + mCurrentMileage;
            double destLng = mCurrentLatLng.longitude;
            double destLat = mCurrentLatLng.latitude;
            // 告诉服务端到达目的地
//            dealWithDistance(tripDistance,destLat,destLng,null,null,null);
            reqArrive(tripDistance, null, null, null, destLng, destLat);
        }
    }

    /**
     * 处理距离,使距离更加的准确
     *
     * @param tripDistance
     * @param destLat
     * @param destLng
     * @param destAddress
     * @param destDetailAddress
     * @param destCity
     */
    private void dealWithDistance(double tripDistance, double destLat, double destLng, String destAddress, String destDetailAddress, String destCity) {
        getMesureDistance(tripDistance, destLat, destLng, destAddress, destDetailAddress, destCity);
    }

    /**
     * 校验距离,如果实际距离与起点和终点距离相距很大,说明距离已经飘点,则上传起点和终点之间的距离
     *
     * @param distance @return
     */
    private double ChackDistance(double distance, double reckonDistance) {
        double chackDistance = 0;
        if (reckonDistance == 0) {
            chackDistance = distance;
        } else {
            if (reckonDistance / 1000d - distance > distance * 0.5 || reckonDistance / 1000d - distance < -(distance * 0.5)) {
                chackDistance = reckonDistance / 1000d;
            } else {
                chackDistance = distance;
            }
        }
        return chackDistance;
    }

    // 告诉服务端到达目的地
    private void reqArrive(double tripDistance, String destAddress, String destDetailAddress,
                           String destCity, double destLng, double destLat) {
        LatLng latLng = new LatLng(mAMapManager.getLastLocation().getLatitude(), mAMapManager.getLastLocation().getLongitude());
        String uploadText = uploadText(OrderStatus.ARRIVE_DEST, BizStatus.EMPTY_DRIVING, latLng, PositionType.CKXC);
//        //如果距离大于行车最大里程数,就传0
//        if (tripDistance > 200) tripDistance = 0;
        mSubscriptions.add(
                mOrderRepository.reqArrive(mOrderUuid, tripDistance, destAddress,
                        destDetailAddress, destCity, destLng, destLat, uploadText)
                        .compose(RxUtil.applySchedulers())
                        .doOnSubscribe(() -> mView.showLoadingView(true))
                        .doAfterTerminate(mView::hideLoadingView)
                        .doOnNext(s -> {
                            EventBus.getDefault().post(new SocketEvent(SocketEvent.ARRIVE_DEST));
                            // 语音（到达目的地）
                            SpeechUtil.speech(mView.getContext(), "已到达目的地，请确认费用。");
                        })
                        .subscribe(s -> {
                            mUserRepository.cleanMileage(mOrderUuid);
                            mView.arriveEnd(mOrderUuid);
                        }, ex -> {
                            mView.resetBtnDisplay(); //重置按键显示
                            showNetworkError(ex, R.string.network_error, mView, mUserRepository);
                        }));
    }

    private String uploadText(int orderStatus, int bizStatus, LatLng latLng, String positionType) {
        AMapLocation lastLocation = mAMapManager.getLastLocation();
        UploadLocationMessage uploadLocationMessage = new UploadLocationMessage();
        uploadLocationMessage.setAppid(mView.getContext().getString(R.string.yueyue_appkey));
        uploadLocationMessage.setBizStatus(bizStatus);
        uploadLocationMessage.setDriverType(mUserRepository.getDriverType());
        uploadLocationMessage.setOrderStatus(orderStatus);
        uploadLocationMessage.setOrderUuid(mOrderUuid);
        uploadLocationMessage.setAreaCode(lastLocation.getAdCode());
        uploadLocationMessage.setLat(latLng.latitude);
        uploadLocationMessage.setLng(latLng.longitude);
        uploadLocationMessage.setPositionType(positionType);
        uploadLocationMessage.setDistance(0d);
        uploadLocationMessage.setAngle(lastLocation.getBearing());
        uploadLocationMessage.setSpeed(lastLocation.getSpeed());
        uploadLocationMessage.setElevation(lastLocation.getAltitude());
        uploadLocationMessage.setAccuracy(lastLocation.getAccuracy());
        uploadLocationMessage.setCarLevelType(mUserRepository.getCarLevelType());
        uploadLocationMessage.setClientUuid(mUserRepository.getLocalDriverUuid());
        uploadLocationMessage.setDriverUuid(mUserRepository.getLocalDriverUuid());
        uploadLocationMessage.setLocationUuid(System.currentTimeMillis() + "");
        uploadLocationMessage.setType(MessageType.UPLOAD_LOCATION);
        return JSON.toJSONString(uploadLocationMessage);
    }
    //更改位置
    private void dealwithAMapNaviLocation(AMapNaviLocation location) {

    }
    //实时导航时
    private void dealwithAMapLocation(AMapLocation aMapLocation) {
        // （0,0）排除
        if (aMapLocation.getLatitude() == 0d || aMapLocation.getLongitude() == 0d) return;
        // 当前点经纬度
        LatLng currentLatLng = new LatLng(aMapLocation.getLatitude(), aMapLocation.getLongitude());
        // 10米以内认为无效
        if (mLastLatLng != null) {
            int lineDistance = (int) AMapUtils.calculateLineDistance(currentLatLng, mLastLatLng);
            if (lineDistance < 10) return;
        }
        mLastLatLng = new LatLng(aMapLocation.getLatitude(), aMapLocation.getLongitude());
        // 保存载客状态下的轨迹点
        if (mVO != null && mVO.subStatus == OrderStatus.DEPART) {
            TraceLocation traceLocation = new TraceLocation();
            traceLocation.setLatitude(aMapLocation.getLatitude());
            traceLocation.setLongitude(aMapLocation.getLongitude());
            traceLocation.setBearing(aMapLocation.getBearing());
            traceLocation.setSpeed(aMapLocation.getSpeed());
            traceLocation.setTime(System.currentTimeMillis());
            UploadOrderEntity entity = new UploadOrderEntity();
            entity.currentPoint = new LatLng(traceLocation.getLatitude(), traceLocation.getLongitude());
            entity.passengerUuid = mVO.getPassengerUuid();
            entity.mileage = mRecordMileage + mKilledMileage + mCurrentMileage;
            entity.uploadTime = traceLocation.getTime();
            entity.accuracy = aMapLocation.getAccuracy();
            mUploadOrderEntity = entity;
            mCarryPassengersTraceList.add(traceLocation);
        }
    }

    /**
     * 通过起点和终点得到距离,然后和将要上传的距离作比较,决定到底上传哪个距离
     *
     * @param tripDistance
     * @param latEnd
     * @param lngEnd
     * @param destAddress
     * @param destDetailAddress
     * @param destCity
     */
    private void getMesureDistance(double tripDistance, double latEnd, double lngEnd, String destAddress, String destDetailAddress, String destCity) {
        //如果经纬度获取不到,不校验距离
        if (latEnd == 0 || lngEnd == 0 || mVO.originLat == 0 || mVO.originLng == 0) {
            reqArrive(tripDistance, destAddress, destDetailAddress, destCity, lngEnd, latEnd);
            return;
        }
        LatLonPoint start = new LatLonPoint(mVO.originLat, mVO.originLng);
        LatLonPoint end = new LatLonPoint(39.908692, 116.397477);
        RouteSearch routeSearch = new RouteSearch(mView.getContext());
        RouteSearch.FromAndTo fromAndTo = new RouteSearch.FromAndTo(start, end);
        RouteSearch.DriveRouteQuery query = new RouteSearch.DriveRouteQuery(fromAndTo, RouteSearch.DRIVING_SINGLE_DEFAULT,
                null, null, "");
        routeSearch.calculateDriveRouteAsyn(query);
        // 路线规划的回调
        routeSearch.setRouteSearchListener(new RouteSearch.OnRouteSearchListener() {
            @Override
            public void onBusRouteSearched(BusRouteResult busRouteResult, int i) {

            }

            @Override
            public void onDriveRouteSearched(DriveRouteResult result, int rCode) {
                if (rCode != 1000) {
                    System.out.println("1111111111" + rCode);
                    reqArrive(tripDistance, destAddress, destDetailAddress, destCity, lngEnd, latEnd);
                } else {
                    float distance1 = result.getPaths().get(0).getDistance();
                    System.out.println("111111111111" + distance1);
                    double v = ChackDistance(tripDistance, distance1);
                    reqArrive(v, destAddress, destDetailAddress, destCity, lngEnd, latEnd);
                    System.out.println(v + "222222222");
                }
            }

            @Override
            public void onWalkRouteSearched(WalkRouteResult walkRouteResult, int i) {

            }

            @Override
            public void onRideRouteSearched(RideRouteResult rideRouteResult, int i) {

            }
        });
    }
}
